
全文搜索可以从海量文本中即时提供准确结果。
它是一种强大的工具,用于查询基于文本的信息,具有快速检索和高相关性。它还可以改善用户体验。
Meilisearch 通常用于电子商务、内容管理系统和法律研究,它通过对文本进行分词并使用 LMDB 有效存储来创建索引。
它使用基于错别字容忍度、邻近度和术语匹配规则的可配置相关性算法对结果进行排名。
想知道它是如何工作的以及为什么它很重要吗?本文将对此进行解释。
什么是全文搜索?
全文搜索是一种强大的搜索技术,它在文本文档或数据集的整个内容中搜索用户查询。它就像一个超级聪明的图书馆员,可以立即扫描图书馆里每本书的每一页,并准确地为你提供你需要的东西。
与特定的关键字匹配算法不同,全文搜索解析整个文档(单个或(如果来自数据库)多个)并找到与用户搜索匹配的所有相关实例。
它深入到传统上可能不被搜索的文档和文档部分,包括产品描述、参考文献和补充材料。解析后,它会索引并存储每个部分的每个单词,使其可用于搜索。
全文搜索有哪些好处?
全文搜索为用户和系统提供了独特的优势。例如,它
- 通过在毫秒内从大型数据集中检索结果,提供高速查询性能。此外,它还分析一组文档中的所有单词并对其进行索引,以加快信息检索速度。
- 通过支持自然语言查询、拼写错误和同义词,增强用户可访问性。因此,它为用户查询提供了直观且用户友好的解决方案。
- 与传统搜索方法相比,提高结果相关性和准确性。它通过排名算法来实现这一点,该算法根据上下文重要性(例如在神经搜索中)和语义相似性而不是简单的单词出现来优先匹配。
这些优势使其在从电子商务到文档管理的应用程序中都具有不可估量的价值。
全文搜索的不同类型有哪些?
全文搜索包含多种方法,每种方法都根据特定需求量身定制。以下是主要类型的概述
基本搜索 | 在所有文档中搜索精确的单词匹配,例如“apple”。然后,它返回所有包含单词“apple”的文档。它高效且节省计算能力,但对于复杂查询缺乏精确性。 |
通配符搜索 | 使用符号(例如,“appl*”)来匹配变体,例如“apply”或“application”。虽然它适用于不完整的输入,但它可能会引入不相关性,例如,当需要“apply”的变体时,返回“apple”。 |
模糊搜索 | 使用相似性算法容忍错误(例如,“appel”匹配“apple”)和非常相似的呈现(例如,“apple”和“apples”)。它非常适合纠正拼写错误或捕获具有细微变体(例如美式英语和英式英语之间)的结果。 |
短语搜索 | 此方法需要精确的序列(例如,带引号的“red apple”)以确保精确的上下文匹配。在搜索特定序列中的精确词串时非常有用。 |
布尔搜索 | 将术语与运算符(例如,“apple **AND **orange **NOT **banana”)结合使用,以更精细地控制结果。它结合了多个搜索字段,缩小了搜索范围,以获得更全面但更具体的结果。 |
邻近搜索 | 指定单词距离(例如,“apple orange”~5,“apple NEAR orange”)以捕获定义范围内的上下文关系。当预期特定单词会出现在一起时,这尤其有用,这使得可以从文档中提取最相关的信息。 |
分面搜索 | 可以从主题的不同方面进行过滤(例如,按“黄色”或“柑橘”细化的“水果”),以精细控制搜索结果。它广泛用于结构化数据集,其中查询具有用户可能正在寻找的特定属性。 |
范围搜索 | 此搜索针对数字(例如,价格:4-20)、字母(例如,尺寸:S-M)或时间范围(例如,日期:24 年 4 月 2 日至 25 年 10 月 2 日)检索用户指定限制内的结果。因此,它对于定量过滤特别有效。 |
每种方法(通常集成到 Meilisearch 等工具中)都能满足各种独特但不同的搜索要求。
这种力量如何在现实世界中体现出来?让我们研究一下这些功能的实际应用。
全文搜索的不同用例有哪些?
全文搜索支持广泛的行业、功能和应用程序。
电子商务搜索 | 通过索引描述、规格和评论来促进产品发现。 | 对于“防水登山靴”等精确查询 |
文档管理系统 | 增强从大量 PDF、Word 文件和其他文本格式的集合中检索。 | 用于访问特定新闻报道等关键信息。 |
客户支持和帮助中心 | 通过索引常见问题解答、文章和故障排除指南,可以快速解决问题。 | 用于使用“修复登录错误”等查询查找解决方案。 |
医学和法律研究 | 在大容量数据中加速对判例法、病历和研究论文的分析。 | 用于获取交通事故案件的判例。 |
社交媒体和内容平台 | 使用文本、字幕和元数据改进新闻网站、博客页面和视频平台的内容索引。 | 用于更好地发现趋势,例如焦糖咖啡。 |
这些应用程序展示了全文搜索是如何高效、多功能信息检索的支柱。
但它是如何从原始数据到可搜索结果的呢?让我们研究一下全文搜索的索引功能。
全文搜索是如何工作的?
在现代搜索引擎中,全文搜索是一个复杂的多步骤过程。其主要目标是相关性和速度,在这里我们将快速分解其工作原理。
在许多搜索系统中,第一步是抓取或摄取要搜索的内容。这可以通过机器人、直接上传文件或通过 API 和数据库来实现。方法的具体组合将取决于用例。例如,Google 依赖爬虫,而公司的内部搜索引擎主要使用数据库或直接摄取文件。
之后,文本需要进行处理和规范化。分词(稍后详细介绍)、小写转换、停用词去除和词干提取等技术可确保文本干净和标准化,因此搜索不会因文本中的微小差异(例如单词的大小写)而遗漏相关结果。
然后是倒排索引,你可以将其视为整个过程的核心。它是一种将术语映射到它们出现的文档的数据结构。
“coffee” → [Doc1, Doc3, Doc5]
“beans” → [Doc3, Doc4]
倒排索引允许快速查找哪些文档包含给定的搜索词,而无需扫描每个文档的全部内容。
除了术语之外,索引还可以存储术语位置(用于短语搜索)、频率数据(术语在文档中出现的频率)以及元数据,例如标题、标签等。
现在,我们进入用户开始搜索的阶段。查询处理要求系统以与倒排索引相同的方式对用户查询进行分词和规范化。在此阶段还可以添加用户意图增强功能,例如同义词匹配。
最后,一旦找到匹配项,就会进行评分和排名。由于并非所有匹配项都同样相关,搜索引擎使用算法根据相关性对结果进行排名和排序。
TF-IDF(词频-逆文档频率)和 BM25(受 TF-IDF 启发但使用概率模型)是排序结果的“经典”方法。现代技术包括基于向量的搜索(语义搜索),它将查询和文档转换为数值向量,以便根据含义而不是关键字进行匹配。
现在我们大致了解了全文搜索的工作原理,我们将以我们自己的 Meilisearch 为例,深入探讨其阶段和技术。
深入了解 Meilisearch 全文搜索过程
索引将原始数据转换为可搜索的格式,这是全文搜索中的关键步骤。Meilisearch 通过结构化方法优化此过程,值得了解其工作原理。
我们将带您逐步了解 Meiliearch 如何处理这些过程。
高性能存储引擎
Meilisearch 采用基于名为“文档”的记录的自定义存储引擎,这些记录分组到名为“索引”的集合中,旨在提高效率和可扩展性。
在幕后,Meiliearch 使用 LMDB(闪电内存映射数据库)键值存储,该存储处理从小型集合到数百万条记录的数据集,并将其存储为键值对的集合。这种存储配置可保持低内存使用率、快速访问时间和高性能,以提供最佳用户体验。
例如,LMDB 通过一次只允许一个写入过程来避免与同步相关的问题。这使其能够为用户提供对最新、一致数据的快速访问。
然而,在键值存储生效之前,Meilisearch 通过分词预处理数据。
从单词到令牌
原始文本,例如产品描述,不会直接转储到数据库中。它首先被分段为令牌:小的可搜索单元——分词的第一个过程。
为此,Meilisearch 使用(并维护)名为 Charabia 的开源分词器。Charabia 允许用户配置他们想要可搜索并随后分词的字段。
分词的第二步是规范化,或者更简单地说,基于规则的组织。由于每种语言都有其自身的特点,这是一项高度特定于语言的任务,其中单词可以小写,并且可以删除变音符号,例如重音。
在以下示例中,“Le café de Nicolas”被分段为“le”、“cafe”、“de”和“nicolas”。Meilisearch 还会去除噪音(停用词,如“the”)并规范化术语(例如从“Le café de Nicolas”到“le cafe de nicolas”)以使其更易于分类。
分段和规范化共同通过使用适当的数据结构组织令牌来使搜索更智能、更快、更不字面。
存储令牌
一旦分词,这些单个令牌就需要一个家。Meilisearch 等现代全文搜索引擎依赖于巧妙的数据结构来实现高效存储和快速检索。
每个功能,如前缀搜索、拼写错误容忍度和地理搜索,都有其优点和缺点。因此,我们的团队仔细关注并选择了最适合我们搜索引擎且不影响速度的功能。
现在让我们看看为 Meilisearch 提供支持的数据结构。
倒排索引
倒排索引是核心技巧。倒排索引将令牌映射到它们所在的文档以及它们在这些文档中的位置。请参阅下图,了解它如何将单词“alice”、“hello”和“word”映射到各自的文档。
它之所以快,是因为顾名思义,它颠覆了通常的文档到单词查找。由于它一次存储单词并将其与它们在倒排索引中出现的文档相关联,因此它不会浏览每个文档来查找搜索到的单词。
Meilisearch 为每个文档索引创建近 20 个倒排索引,使其成为最常出现的数据结构之一。然而,为了提供即时搜索体验,引擎需要进行大量预处理并在索引期间定义搜索模式,包括单词前缀、可过滤属性等。
Roaring bitmap
Meilisearch 使用 roaring bitmap 来压缩与每个令牌关联的文档 ID 列表。它们内存占用小但查询速度快,非常适合扩展到大型数据集。
此外,它们存储大量的整数集并执行集合操作,如并集、交集和差集。这些操作有助于通过根据文档的相互关系选择文档来优化搜索结果。
有限状态转换器
有限状态转换器 (FST) 以紧凑、依赖于字符串的方式存储令牌前缀和变体。它们表示按升序词典(字母或数字)排列的字符串的状态序列。由于其紧凑性,它们是倒排索引的更小更快的替代方案。
FST 有时被称为单词词典,因为它包含数据集中的所有索引单词。Meilisearch 利用两个主要的 FST:一个用于存储数据集的所有单词,另一个用于存储最常出现的前缀。
Meilisearch 对 FST 的依赖使其能够支持压缩和延迟解压缩技术,同时还能以最小的开销处理通配符或自动完成。这包括通过使用正则表达式般的自动机检索匹配特定语法规则或模式(例如前缀)的单词子集。
R-tree
R-tree 管理空间或基于范围的数据,例如坐标或数值,为 Meilisearch 的地理搜索功能提供支持。
为了优化“5 英里内的餐馆”等全文搜索查询,R-tree 将地理坐标与相关文档标识符相关联。这允许用户查找特定区域内的附近点或与其他空间对象相交的点。
这些组件共同使索引快速灵活。但当你点击“搜索”时会发生什么?以下部分将准确说明在搜索时如何处理搜索词。
搜索时间:查询处理
索引为舞台搭建,查询处理才是主角。当你输入查询时,Meilisearch 不会只是随机返回匹配项;它是经过深思熟虑和精确的。
现代搜索体验只需要您开始输入即可获得结果。为了实现这种即时搜索体验,Meilisearch 预先计算了最常见前缀的列表,以便立即生成它们。
为了实现拼写容错,Meilisearch 使用 FST 和 Levenshtein 算法。该算法计算 Levenshtein 距离或将一个字符串转换为另一个字符串的“成本”。换句话说,它量化了将一个单词转换为另一个单词所需的转换次数。
例如,转换形式可以是
- 插入,例如,hat -> chat
- 删除,例如,tiger -> tier
- 替换,例如,cat -> hat
- 换位或交换,例如,scared -> sacred
FST 在用户指定的编辑距离内生成单词的所有可能变体。因此,它们使搜索引擎能够准确计算 Levenshtein 距离并通过将用户输入与“有效”单词词典进行比较来检测拼写错误。
在处理搜索请求时,会考虑用户是否已完成输入或查询是否有任何拼写错误等问题。
查询图
每次收到搜索查询时,Meilisearch 都会将其解析为概述术语及其关系的图结构。这种结构让 Meilisearch 可以规划获取结果的最快方式。
例如,查询“the sun flower”被拆分为“the”、“sun”和“flower”,逻辑连接(例如 AND)指导搜索路径。此外,它可以通过以下方式转换:
- 连接:the sunflower
- 替换:the sun flowed
- 添加:the sun flowers
更复杂的查询,例如“the sun flower is facing the su”,将以更扩展的方式处理(图表由我们的 D2 驱动的内部调试工具提供)
如上图所示,该图表示搜索查询的不同变体。引擎预先计算查询中每个术语的单词变体(及其 Levenshtein 距离)。此外,它还确定查询中的最后一个术语是否是前缀,即后面没有空格,以便调用前缀数据库。
现在你有一个查询图,你用它做什么?
在过滤阶段,Meilisearch 将潜在结果缩小到在索引过程中生成的符合过滤条件的文档 ID。
接下来,它使用查询术语及其查询图变体,并在 FST 中搜索匹配的单词。如果该单词被视为前缀,它还将在前缀 FST 中查找它。它在**倒排索引**中搜索它们以检索相应的文档 ID。
最后,引擎执行交集以识别包含查询图中的单词并满足过滤条件的文档。
让我们举一个例子来更好地理解查询处理。假设你有一个歌曲数据集,用户搜索“John Lennon”。用户只想检索 1957 年至 1975 年间发行的 John Lennon 歌曲。
首先,Meilisearch 检索该时间段内歌曲的文档 ID。在确保查询图中的单词存在于 FST 中后,Meilisearch 检索包含 John、Lennon 或 两者 的文档 ID。它还会检索可能的变体,但为简单起见,我们将其省略。
最后,只考虑两组文档 ID 的重叠(子集)。这意味着只保留同时出现在两组中的文档 ID。换句话说,Meilisearch 保留 1957 年至 1975 年间发行且包含 John、Lennon 或 两者 的歌曲的文档 ID。
但是当一整列表的文档与搜索查询匹配时会发生什么?引擎如何决定哪个更相关,从而成为第一个搜索结果?
这就是相关性计算发挥作用的地方。
相关性
并非所有匹配都相同。例如,也可能会出现 John Lebon 等单词变体。这就是为什么 Meilisearch 使用词频(“John”出现的频率)、邻近度(“John”和“Lennon”是否接近?)和字段权重(标题优先于正文)等因素对搜索结果进行排名。
它被调整得让人感觉直观,这样最好的内容就能排在最前面。这种智能解析和排名的结合使搜索变得快速而准确。
Meilisearch 使用桶排序对搜索结果中的文档进行排序。此算法允许根据一组规则对文档进行排名。默认情况下,Meilisearch 按以下顺序优先处理规则
- 匹配词数:包含所有查询词的文档优先排名
- 错别字数量:拼写错误较少的匹配查询词的文档优先排名
- 匹配查询词之间的邻近度:查询词出现位置接近且顺序与查询字符串相同的文档优先排名
- 查询词在属性中的存在和位置:查询词在更重要属性中且在属性开头出现的文档优先排名
- 用户定义参数:在查询时满足用户设置条件的文档优先排名
- 关键词匹配:与查询匹配的单词数量较多的文档优先排名
Meilisearch 依次应用这些规则,逐步排序结果。如果两个文档在应用一条规则后并列,它会使用下一条规则来打破平局。
请注意,这些规则是完全可定制的,这意味着您可以根据需要添加、删除和重新排序它们。在相关性文档中阅读更多内容。
默认情况下,Meilisearch 每次搜索最多返回 1000 个文档。但是,它优先提供最相关的结果,而不是所有匹配结果。通过这种方式,Meilisearch 优先考虑效率和准确性,而不是穷尽结果,以确保优化的搜索体验。
常见问题 (FAQs)
全文搜索与基于关键词的搜索有何不同?
全文搜索扫描整个文档以查找匹配项,并理解语义上下文和相关性。另一方面,传统的基于关键词的搜索只在特定字段中查找精确的术语,而忽略任何其他相关实例。因此,全文搜索提供了更大的深度、适应性和精细度,使其非常适合自然语言查询。
全文搜索有哪些缺点?
全文搜索需要大量的存储和计算资源进行索引,使其资源消耗大。如果未经优化,它可能会缓慢处理复杂查询或返回不相关甚至虚假的结果。
有哪些流行的全文搜索引擎?
Meilisearch 是一个流行的选项,用于提供快速、用户友好的搜索功能。其他包括 Elasticsearch(功能强大但复杂)、Solr(以企业为中心)和 Algolia(优化易用性)。
全文搜索与向量搜索有何不同?
全文搜索侧重于基于文本的数据集中的文本匹配和关键词相关性,而向量搜索使用机器学习来识别语义相似性。虽然它们各自都功能强大,但它们服务于不同但互补的目的。
全文搜索有哪些替代方案?
全文搜索的一种替代方案是针对基于意义的检索的向量搜索。其他选项包括用于结构化数据类型的 SQL 查询和用于处理小规模模式匹配的正则表达式。每种方法都适用于特定的用例,因此适合一种应用程序的方法可能不适合另一种应用程序。
通过全文搜索提供最佳结果
全文搜索是一种强大的搜索机制,用于访问和管理海量文本数据。其速度、灵活性和相关性支持从电子商务到研究的各种应用。
Meilisearch 通过高效的索引和复杂的查询处理进一步提升了这一点。它不仅仅是查找东西;它旨在快速找到正确的东西。像倒排索引和相关性算法这样的结构有助于分词或排名结果。